<template>
    <div class="base-floating_wrap">
        <div style="display: flex; align-items: center;">
            <h3>演示方式</h3>
            <RadioGroup v-model="methodValue" class="custom-radio-group" @on-change="onMethodChange">
                <Radio label="hover">鼠标悬浮提示</Radio>
                <Radio label="click">点击切换位置</Radio>
            </RadioGroup>
        </div>
        <RadioGroup class="custom-radio-group" v-model="alignmentWay" @on-change="onRadioChange">
            <Radio v-for="(item, index) in placementList" :key="index" :label="item">{{ item }}</Radio>
        </RadioGroup>
        <div class="tooltip__widget">
            <button ref="buttonRef" id="button" aria-describedby="tooltip">
                My button
            </button>
            <div ref="tooltipRef" id="tooltip" role="tooltip">
                My tooltip with more content
                <div ref="arrowRef" id="arrow"></div>
            </div>
        </div>
    </div>
</template>

<script setup>
import { computePosition, flip, shift, offset, arrow } from "@floating-ui/vue";

const buttonRef = ref(null)
const tooltipRef = ref(null)
const arrowRef = ref(null)
const methodValue = ref('hover')
const alignmentWay = ref('top')
const placementList = ref([
    'top-start',
    'top',
    'top-end',
    'right-start',
    'right',
    'right-end',
    'bottom-start',
    'bottom',
    'bottom-end',
    'left-start',
    'left',
    'left-end',
])


function onMethodChange(params) {
    console.log(methodValue.value);
    if (methodValue.value==='hover') {
        registerListener()
    } else {
        tooltipRef.value.style.display = 'block';
        [
            ['mouseenter', showTooltip],
            ['mouseleave', hideTooltip],
            ['focus', showTooltip],
            ['blur', hideTooltip],
        ].forEach(([event, listener]) => {
            buttonRef.value.removeEventListener(event, listener, false);
        });
    }
}

function onRadioChange(params) {
    update()
    console.log(alignmentWay.value);
}

/**
 * flip() 自动定位元素位置，第一次加载的时候，解决元素溢出文档边界问题
 * shift() 1、当提示内容过多，解决提示框在按钮中心对齐，多余部分会超出视图边界，无法查看，自动切换元素位置，完整展示
 *         2、将工具提示从底部居中的位置移动，直到完全显示在视图中
 * offset() 倾斜值，解决元素齐平参考元素问题，让提示文本于按钮保持5px的距离
 */
function update(params) {
    computePosition(buttonRef.value, tooltipRef.value, {
        placement: alignmentWay.value || "top",
        strategy: 'absolute',
        middleware: [
            flip(),
            shift({ padding: 5 }),
            offset(6),
            arrow({ element: arrowRef.value })
        ]
    }).then(({ x, y, placement, middlewareData }) => {
        Object.assign(tooltipRef.value.style, {
            left: `${x}px`,
            top: `${y}px`
        })
        // 访问箭头中间件参数
        const {x: arrowX, y: arrowY } = middlewareData.arrow
        const staticSide = {
            top: 'bottom',
            right: 'left',
            bottom: 'top',
            left: 'right',
        }[placement.split('-')[0]];

        // 动态修改箭头x, y 坐标值
        // x is the x-axis offset, only existing if the placement is vertical ('top' or 'bottom').
        // y is the y-axis offset, only existing if the placement is horizontal ('right' or 'left').
        // console.log(arrowRef.value.style, 7477);
        Object.assign(arrowRef.value.style, {
            left: arrowX != null ? `${arrowX}px` : '',
            top: arrowY != null ? `${arrowY}px` : '',
            right: '',
            bottom: '',
            [staticSide]: '-4px',
        });
    })
}

function showTooltip(params) {
    tooltipRef.value.style.display = 'block'
    update()
}
function hideTooltip(params) {
    tooltipRef.value.style.display = 'none'
}

function registerListener () {
    [
        ['mouseenter', showTooltip],
        ['mouseleave', hideTooltip],
        ['focus', showTooltip],
        ['blur', hideTooltip],
    ].forEach(([event, listener]) => {
        buttonRef.value.addEventListener(event, listener);
    });
}

nextTick(() => {
    registerListener()
})

</script>

<style lang="scss" scoped>
.base-floating_wrap {
    position: relative;
    overflow: hidden;
    padding: 0.5rem;
    height: 20rem;
    border-radius: 5px;
    border: 1px #cccccc solid;
    display: flex;
    flex-direction: column;
    align-items: center;
    .custom-radio-group {
        label {
            padding: 0.8rem;
        }
    }
    .tooltip__widget {
        margin-top: 1.5rem;
    }
}
#button {
    padding-right: 0.5rem;
    padding-left: 0.5rem;
    background-color: #10ac84;
    border-radius: 0.25rem;
    box-sizing: border-box;
    border: 0 solid #10ac84;
    font-size: 20px;
    letter-spacing: 3px;
    height: 5rem;
    color: #fff;
}
#tooltip {
    display: none;
    width: max-content;
    position: absolute;
    top: 0;
    left: 0;
    background: #222;
    color: white;
    font-weight: bold;
    padding: 0.25rem;
    border-radius: 4px;
    font-size: 90%;
}
#arrow {
  position: absolute;
  background: #222;
  width: 8px;
  height: 8px;
  transform: rotate(45deg);
}
</style>